package fnsvr

import "sync"

//读写锁 用于简化锁代码

//本类非线程安全，不可夸协程访问同个实例

type RWMutexProxyState int

const (
	RWMutexProxyStateUnlock = iota + 1 //未锁定
	RWMutexProxyStateRLock             //只读锁定
	RWMutexProxyStateWLock             //写锁定
)

type RWMutexProxy struct {
	rw *sync.RWMutex
	st RWMutexProxyState
}

// 创建互斥代理对象
func NewRWMutexProxy(rw *sync.RWMutex) *RWMutexProxy {
	return &RWMutexProxy{rw: rw, st: RWMutexProxyStateUnlock}
}

// 创建互斥代理对象，并设置为已经获得读锁
func NewRWMutexProxyRLocked(rw *sync.RWMutex) *RWMutexProxy {
	return &RWMutexProxy{rw: rw, st: RWMutexProxyStateRLock}
}

func (myself *RWMutexProxy) TryRLock() bool {
	if myself.st == RWMutexProxyStateRLock || myself.st == RWMutexProxyStateWLock {
		return true
	}

	if myself.rw.TryRLock() {
		myself.st = RWMutexProxyStateRLock
		return true
	}

	return false
}

func (myself *RWMutexProxy) RLock() {
	if myself.st == RWMutexProxyStateRLock || myself.st == RWMutexProxyStateWLock {
		return
	}

	myself.rw.RLock()
	myself.st = RWMutexProxyStateRLock
}

// 写锁，或从读锁提升为写锁（提升过程别的协程会并行执行）
func (myself *RWMutexProxy) Lock() {
	if myself.st == RWMutexProxyStateWLock {
		return
	}

	myself.Unlock()
	myself.rw.Lock()
	myself.st = RWMutexProxyStateWLock
}

func (myself *RWMutexProxy) Unlock() {
	switch myself.st {
	case RWMutexProxyStateUnlock:
		return
	case RWMutexProxyStateRLock:
		myself.rw.RUnlock()
		myself.st = RWMutexProxyStateUnlock
		return
	case RWMutexProxyStateWLock:
		myself.rw.Unlock()
		myself.st = RWMutexProxyStateUnlock
		return
	}
}
